package cn.com.chengmandian.bike.service.impl;

import cn.com.chengmandian.bike.model.*;
import cn.com.chengmandian.bike.mapper.EbRideCloseMapper;
import cn.com.chengmandian.bike.service.*;
import cn.com.chengmandian.core.common.constants.CommonConstant;
import cn.com.chengmandian.core.redis.cache.AgentParamCacheService;
import cn.com.chengmandian.core.web.exceptions.BadResponseException;
import cn.com.chengmandian.core.web.pojo.AjaxResult;
import cn.com.chengmandian.core.web.pojo.BikeAreaParam;
import cn.com.chengmandian.service.bike.IotBikeClient;
import cn.com.chengmandian.service.bike.constants.BikeHelmetInstallEnum;
import cn.com.chengmandian.service.bike.constants.DeviceCommandEnum;
import cn.com.chengmandian.service.bike.constants.RideOrderStatusEnum;
import cn.com.chengmandian.service.bike.constants.UserTypeEnum;
import cn.com.chengmandian.service.bike.form.SendBikeCommandForm;
import cn.com.chengmandian.service.bike.pojo.CloseLockRequest;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.Date;

/**
 * <p>
 * 电单车运营-订单停车关锁行为记录 服务实现类
 * </p>
 *
 * @author AutoGenerator
 * @since 2024-10-26
 */
@Slf4j
@Service
public class EbRideCloseServiceImpl extends ServiceImpl<EbRideCloseMapper, EbRideClose> implements IEbRideCloseService {

    @Autowired
    private IEbDeviceBikeService deviceBikeService;
    @Autowired
    private AgentParamCacheService agentParamCacheService;
    @Autowired
    private IEbPriceRuleService priceRuleService;
    @Autowired
    private IEbRideOrderService rideOrderService;
    @Autowired
    private IEbOperationStationService operationStationService;
    @Autowired
    private IotBikeClient iotBikeClient;
    @Autowired
    private IEbRideHelmetService rideHelmetService;

    @Override
    public EbRideClose getByOrderCode(String orderNo) {
        return this.getOne(new LambdaQueryWrapper<EbRideClose>()
                .eq(EbRideClose::getOrderNo, orderNo)
                .orderByDesc(EbRideClose::getId)
                .last("limit 0,1"));
    }

    /**
     * 运维结束车辆，生成停车记录
     */
    @Override
    public void opsCloseOrder(EbRideClose rideClose, Integer orderId, Integer closeReason, Integer opsUserId, String opsUserName, BigDecimal customOrderMoney) {
        EbRideOrder rideOrder = rideOrderService.getById(orderId);
        Assert.notNull(rideOrder, "订单不存在");
        Assert.isTrue(rideOrder.getStatus().equals(RideOrderStatusEnum.RIDING.getCode())
                || rideOrder.getStatus().equals(RideOrderStatusEnum.PAUSE.getCode()), "订单已结束");
        this.closeCheck(rideClose, rideOrder, CommonConstant.ONE, CommonConstant.ONE, CommonConstant.ONE, false, UserTypeEnum.OPS.getCode(), opsUserId, opsUserName, null, null);
        this.endCheck(rideClose, "运维端强制结束订单");
        this.save(rideClose);
    }

    /**
     * 运营结束车辆，生成停车记录
     */
    @Override
    public void agentCloseOrder(EbRideClose rideClose, Integer orderId, Integer agentUserId, String agentUserName, BigDecimal customOrderMoney) {
        EbRideOrder rideOrder = rideOrderService.getById(orderId);
        Assert.notNull(rideOrder, "订单不存在");
        Assert.isTrue(rideOrder.getStatus().equals(RideOrderStatusEnum.RIDING.getCode())
                || rideOrder.getStatus().equals(RideOrderStatusEnum.PAUSE.getCode()), "订单已结束");
        this.closeCheck(rideClose, rideOrder, CommonConstant.ONE, CommonConstant.ONE, CommonConstant.ONE, false, UserTypeEnum.AGENT.getCode(), agentUserId, agentUserName, null, null);
        this.endCheck(rideClose, "运营端强制结束订单");
        this.save(rideClose);
    }

    /**
     * 系统结束车辆，生成停车记录
     */
    @Override
    public void sysCloseOrder(EbRideClose rideClose, Integer orderId, String systemName) {
        EbRideOrder rideOrder = rideOrderService.getById(orderId);
        Assert.notNull(rideOrder, "订单不存在");
        Assert.isTrue(rideOrder.getStatus().equals(RideOrderStatusEnum.RIDING.getCode())
                || rideOrder.getStatus().equals(RideOrderStatusEnum.PAUSE.getCode()), "订单已结束");
        this.closeCheck(rideClose, rideOrder, CommonConstant.ONE, CommonConstant.ONE, CommonConstant.ONE, false, UserTypeEnum.SYS.getCode(), 0, StrUtil.isBlank(systemName)? "系统" : systemName, null, null);
        this.endCheck(rideClose, "系统强制结束订单");
        this.save(rideClose);
    }

    /**
     * 用户一键还车，生成停车记录
     * @param rideClose
     * @param bikeId
     */
    @Override
    public void bikeCloseOrder(EbRideClose rideClose, Integer bikeId) {
        EbRideOrder rideOrder = rideOrderService.getByBike(bikeId);
        Assert.notNull(rideOrder, "订单不存在");
        Assert.isTrue(rideOrder.getStatus().equals(RideOrderStatusEnum.RIDING.getCode())
                || rideOrder.getStatus().equals(RideOrderStatusEnum.PAUSE.getCode()), "订单已结束");
        this.closeCheck(rideClose, rideOrder, CommonConstant.ZERO, CommonConstant.ZERO, CommonConstant.ZERO, true, UserTypeEnum.SYS.getCode(), 0, "一键还车",null, null);
        this.endCheck(rideClose, "用户一键还车结束订单");
        this.save(rideClose);
    }

    /**
     * 停车检查数据初始化
     */
    @Override
    public void closeCheck(EbRideClose rideClose, EbRideOrder rideOrder, Integer isDispatch, Integer payHelmetMoney, Integer aiPhotosPass,
                           boolean isMember, Integer closeUserType, Integer closeUserId, String closeUserName,BigDecimal memberLng, BigDecimal memberLat) {
        rideClose.setAreaId(rideOrder.getAreaId());
        rideClose.setOrderId(rideOrder.getId());
        rideClose.setOrderNo(rideOrder.getOrderNo());
        rideClose.setCloseUserType(closeUserType);
        rideClose.setCloseUserId(closeUserId);
        rideClose.setCloseUserName(closeUserName);
        rideClose.setMemberId(rideOrder.getMemberId());
        rideClose.setMemberLng(memberLng);
        rideClose.setMemberLat(memberLat);

        // 车辆信息
        EbDeviceBike deviceBike = deviceBikeService.getByNo(rideOrder.getBikeNo());
        rideClose.setBikeId(deviceBike.getId());
        rideClose.setBikeNo(deviceBike.getBikeNo());
        rideClose.setLng(deviceBike.getLng());
        rideClose.setLat(deviceBike.getLat());
        rideClose.setLicensePlate(deviceBike.getLicensePlate());
        if(deviceBike.getStationId() != null) {
            EbOperationStation operationStation = operationStationService.getById(deviceBike.getStationId());
            Assert.notNull(operationStation, "站点不存在");
            rideClose.setStationId(operationStation.getId());
            rideClose.setStationName(operationStation.getName());
        }

        // 停车车辆检查
        this.checkCloseBike(isMember, rideOrder, rideClose, deviceBike, isDispatch, payHelmetMoney, aiPhotosPass, closeUserId, closeUserName);
    }

    /**
     * V3还车，实际车辆检查逻辑
     */
    @Override
    public void checkCloseBike(Boolean isMember, EbRideOrder rideOrder, EbRideClose rideClose, EbDeviceBike deviceBike, Integer isDispatch, Integer payHelmetMoney, Integer aiPhotosPass, Integer userId, String userName) {
        // 用户暂未接受调度费用
        EbPriceRule priceRule = priceRuleService.getRule(deviceBike.getAreaId());

        BikeAreaParam bikeAreaParam = agentParamCacheService.getParam(deviceBike.getAgentId(), deviceBike.getAreaId());

        // 禁停区检测
        rideClose.setNoparkingCheckResult(CommonConstant.ONE);
        if (deviceBike.getNoparkingId() != null) {
            rideClose.setNoparkingCheckResult(CommonConstant.ZERO);
            if(isMember) {
                // 发送还车失败语音
                this.sendStopBikeVoice(deviceBike.getAgentId(), deviceBike.getBikeNo(), "禁停区还车提醒");
                throw new BadResponseException(503, "当前处于禁停区，请到P点停车");

            // 禁停区内自动停车 记录调度费
            } else {
                rideClose.setAreaCheckResult(CommonConstant.ONE);
                rideClose.setPayDispatchMoney(isDispatch);
                rideClose.setDispatchType(CommonConstant.THREE);
                rideClose.setDispatchMoney(priceRule.getNoparkingDispatchFee());
            }
        }

        // 头盔检测
        rideClose.setHelmetCheckResult(CommonConstant.TWO);
        // 头盔检测
        if(!rideHelmetService.checkReturnBikeHelmet(bikeAreaParam, deviceBike, rideOrder)) {
            checkBikeHelmet(isMember, rideClose, payHelmetMoney, priceRule, deviceBike);
        }

        // 服务区检测
        this.checkOperationArea(isMember, rideClose, deviceBike, isDispatch, priceRule);

        // 站点检测 车辆超区或者在禁停区就不验证是否在站点内
        if(deviceBike.getIsInArea() != null && deviceBike.getIsInArea().equals(CommonConstant.ONE) && deviceBike.getNoparkingId() == null) {
            // 检查站点信息
            this.checkOperationStation(isMember, rideClose, deviceBike, isDispatch, priceRule);

            // 停车站点rfid停车检查
            this.checkOperationStationRfid(isMember, rideClose, bikeAreaParam, deviceBike, isDispatch, priceRule);

            // 停车规范行为检查
            this.checkStopBikeStandard(isMember, rideClose, deviceBike, bikeAreaParam, priceRule, isDispatch, aiPhotosPass);
        }

        // 处理调度费减免
        this.handleDispatchReduceMoney(isMember, rideClose, rideOrder, priceRule);
    }

    @Override
    public void checkStopBikeStandard(Boolean isMember, EbRideClose rideClose, EbDeviceBike deviceBike, BikeAreaParam bikeAreaParam, EbPriceRule priceRule,
                                      Integer isDispatch, Integer aiPhotosPass) {
        if(deviceBike.getStationId() != null) {
            // 站点配置规范停车
            EbOperationStation operationStation = operationStationService.getById(deviceBike.getStationId());
            if(operationStation != null){
                if (operationStation.getCameraStopEnabled() != null && operationStation.getCameraStopEnabled().equals(CommonConstant.ONE)) {
                    bikeAreaParam.setUserCameraAIStopBike(true);
                    if (operationStation.getCameraStopDistance() != null && operationStation.getCameraStopDistance() > 0) {
                        bikeAreaParam.setUserCameraStopAngle(operationStation.getCameraStopDistance());
                    }
                    if (operationStation.getCameraStopAngle() != null && operationStation.getCameraStopAngle() > 0) {
                        bikeAreaParam.setUserCameraStopAngle(operationStation.getCameraStopAngle());
                    }
                    if(operationStation.getCameraStopDistance() != null && operationStation.getCameraStopDistance() > 0) {
                        bikeAreaParam.setUserCameraStopDistance(operationStation.getCameraStopDistance());
                    }
                } else if (operationStation.getCameraStopEnabled() != null && operationStation.getCameraStopEnabled().equals(CommonConstant.ZERO)) {
                    bikeAreaParam.setUserCameraAIStopBike(false);
                }
                if (operationStation.getSpikeStopEnabled() != null && operationStation.getSpikeStopEnabled().equals(CommonConstant.ZERO)) {
                    bikeAreaParam.setUserSpikeStopBike(false);
                } else if (operationStation.getSpikeStopEnabled() != null && operationStation.getSpikeStopEnabled().equals(CommonConstant.ONE)) {
                    bikeAreaParam.setUserSpikeStopBike(true);
                    if (operationStation.getSpikeSignalStrength() != null && operationStation.getSpikeSignalStrength() > 0) {
                        bikeAreaParam.setUserSpikeSignalStrength(operationStation.getSpikeSignalStrength());
                    }
                }
            }
        }
        // 区域配置规范停车
        this.areaConfigCheck(isMember, deviceBike.getAgentId(),rideClose, bikeAreaParam, deviceBike.getBikeNo(), priceRule, isDispatch, aiPhotosPass);
    }

    private void areaConfigCheck(Boolean isMember, Integer agentId, EbRideClose rideClose, BikeAreaParam bikeAreaParam, String bikeNo, EbPriceRule priceRule,
                                 Integer isDispatch, Integer aiPhotosPass){
        // 停车规范检查结果 默认-1 未执行
        if(rideClose.getCloseCheckResult() == null) {
            rideClose.setCloseCheckResult(-1);
        }
        // 停车规范检查项
        JSONObject closeCheckItem = new JSONObject();
        if(StrUtil.isNotBlank(rideClose.getCloseCheckItem())) {
            closeCheckItem = JSONObject.parseObject(rideClose.getCloseCheckItem());
        }
        // 停车规范检查结果
        String closeCheckRule = rideClose.getCloseCheckRule();

        // 是否满足停车规范规则
        Boolean stopStandard = true;
        Integer errCode = 500;
        if(bikeAreaParam.getUserCameraAIStopBike() || bikeAreaParam.getUserSpikeStopBike()) {
            rideClose.setCloseCheckResult(CommonConstant.ONE);
            AjaxResult res = null;
            if (bikeAreaParam.getUserCameraAIStopBike()) {
                CloseLockRequest closeLockRequest = new CloseLockRequest();
                closeLockRequest.setIsCameraStop(CommonConstant.ONE);
                closeLockRequest.setCameraStopAngle(bikeAreaParam.getUserCameraStopAngle());
                closeLockRequest.setCameraStopColour(bikeAreaParam.getUserCameraStopColor());
                closeLockRequest.setCameraStopDistance(bikeAreaParam.getUserCameraStopDistance());
                closeCheckItem.put("userCameraAIStopBike", bikeAreaParam.getUserCameraAIStopBike());
                closeCheckItem.put("userCameraStopAngle", bikeAreaParam.getUserCameraStopAngle());
                closeCheckItem.put("userCameraStopDistance", bikeAreaParam.getUserCameraStopDistance());
                closeCheckItem.put("userCameraStopColor", bikeAreaParam.getUserCameraStopColor());
                res = iotBikeClient.cameraCloseQuery(agentId, bikeNo, closeLockRequest);
                closeCheckRule = JSONObject.toJSONString(res);
            }
            if (bikeAreaParam.getUserCameraAIStopBike() && res != null && !res.isSuccess()) {
                if(isDispatch == null || isDispatch.equals(CommonConstant.ZERO)) {
                    deviceBikeService.noInStopAreaSendVoice(agentId, bikeNo, "摄像头停车失败提醒");
                }
                stopStandard = false;
                errCode = 508;
            }
            if (stopStandard && bikeAreaParam.getUserSpikeStopBike()) {
                closeCheckItem.put("userSpikeStopBike", bikeAreaParam.getUserSpikeStopBike());
                closeCheckItem.put("userSpikeSignalStrength", bikeAreaParam.getUserSpikeSignalStrength());
                res = iotBikeClient.beaconsQuery(agentId, bikeNo, bikeAreaParam.getUserSpikeSignalStrength());
                closeCheckRule = JSONObject.toJSONString(res);
                if (res != null && !res.isSuccess()) {
                    if(isDispatch == null || isDispatch.equals(CommonConstant.ZERO)) {
                        deviceBikeService.noInStopAreaSendVoice(agentId, bikeNo, "道钉停车失败提醒");
                    }
                    stopStandard = false;
                    errCode = 509;
                }
            }

            if ((bikeAreaParam.getUserCameraAIStopBike() || bikeAreaParam.getUserSpikeStopBike()) && res == null) {
                if(isDispatch == null || isDispatch.equals(CommonConstant.ZERO)) {
                    deviceBikeService.noInStopAreaSendVoice(agentId, bikeNo, "规范停车失败提醒");
                }
                stopStandard = false;
            }
        }
        rideClose.setCloseCheckRule(closeCheckRule);
        // 不满足停车规范规则视为站外停车
        if(!stopStandard) {
            rideClose.setAreaCheckResult(CommonConstant.ONE);
            rideClose.setDispatchType(CommonConstant.ONE);
            rideClose.setCloseCheckResult(CommonConstant.ZERO);
            BigDecimal stationDispatchFee = BigDecimal.ZERO;
            if(priceRule.getIsOpenDispatch().equals(CommonConstant.ONE)) {
                if(priceRule.getStationDispatchFee().compareTo(BigDecimal.ZERO) > 0) {
                    if (isDispatch == null || isDispatch.equals(CommonConstant.ZERO)) {
                        stationDispatchFee = priceRule.getStationDispatchFee();
                        JSONObject data = new JSONObject();
                        data.put("fee", stationDispatchFee);
                        throw new BadResponseException(errCode, "请规范停车，停车需支付" + stationDispatchFee + "元调度费", data);
                    }
                    stationDispatchFee = priceRule.getStationDispatchFee();
                }
            } else {
                throw new BadResponseException(errCode, "请按照提示规范停车");
            }
            rideClose.setPayDispatchMoney(isDispatch);
            rideClose.setDispatchMoney(stationDispatchFee);
        }
        // 如果开通了AI拍照规范停车 抛出异常代码引导用户AI拍照停车 同意调度费则不开启AI拍照停车
        if(isMember) {
            if ((aiPhotosPass == null || aiPhotosPass.equals(CommonConstant.ZERO))) {
                if (isDispatch == null || isDispatch.equals(CommonConstant.ZERO)) {
                    if (bikeAreaParam.getUserRideAIPhotosStopBike()) {
                        rideClose.setCloseCheckResult(CommonConstant.ONE);
                        closeCheckItem.put("userRideAIPhotosStopBike", bikeAreaParam.getUserRideAIPhotosStopBike());
                        closeCheckItem.put("userAIPhotosStopBikeScheme", bikeAreaParam.getUserAIPhotosStopBikeScheme());
                        closeCheckItem.put("userAIPhotosStopApiParams", bikeAreaParam.getUserAIPhotosStopApiParams());
                        rideClose.setCloseCheckItem(closeCheckItem.toJSONString());
                        throw new BadResponseException(524, "区域开启AI拍照停车");
                    }
                }
            }
        }
        rideClose.setCloseCheckItem(closeCheckItem.toJSONString());
    }

    @Override
    public void handleDispatchReduceMoney(Boolean superRole, EbRideClose rideClose, EbRideOrder rideOrder, EbPriceRule priceRule) {
        // 强制还车不减免调度费
        if(!superRole) return;
        // 有禁停区调度费 不处理
        if(rideClose.getNoparkingCheckResult() != null && rideClose.getNoparkingCheckResult().equals(CommonConstant.ZERO)) return;
        // 区内停车结果 通过 未检查 不处理
        if(rideClose.getAreaCheckResult() == null || !rideClose.getAreaCheckResult().equals(CommonConstant.ONE)) return;
        // 调度类型区外或者无 不处理
        if(rideClose.getDispatchType() == null || !rideClose.getDispatchType().equals(CommonConstant.TWO)) return;
        // 无调度金额 不处理
        if(rideClose.getDispatchMoney() == null || rideClose.getDispatchMoney().compareTo(BigDecimal.ZERO) <= 0) return;

        BigDecimal dispatchReduceMoney = BigDecimal.ZERO;
        // 有调度费
        if (priceRule.getStationDispatchFee().compareTo(BigDecimal.ZERO) > 0) {
            // 如果首次站外减免开启
            if (priceRule.getStationFirstPrevent().equals(CommonConstant.ONE)) {
                EbRideOrder first = rideOrderService.getFirstStationDispatch(rideOrder.getMemberId(), rideOrder.getAreaId());
                if (first == null) {
                    dispatchReduceMoney = priceRule.getStationDispatchFee();
                }
            }
        }
        rideClose.setDispatchFreeMoney(dispatchReduceMoney);
        rideClose.setDispatchMoney(rideClose.getDispatchMoney().subtract(dispatchReduceMoney));
    }

    private void checkOperationStationRfid(Boolean isMember, EbRideClose rideClose, BikeAreaParam bikeAreaParam, EbDeviceBike deviceBike, Integer isDispatch, EbPriceRule priceRule) {
        if(deviceBike.getStationId() != null) {
            EbOperationStation station = operationStationService.getById(deviceBike.getStationId());
            Assert.notNull(station, "车辆定位站点异常");
            if (station.getRfidStopEnabled() != null && station.getRfidStopEnabled() >= CommonConstant.ZERO) {
                if (bikeAreaParam != null && station.getRfidStopEnabled().equals(CommonConstant.ONE)) {
                    bikeAreaParam.setUserStopBikeRfidEnabled(true);
                } else if (bikeAreaParam != null && station.getRfidStopEnabled().equals(CommonConstant.ZERO)) {
                    bikeAreaParam.setUserStopBikeRfidEnabled(false);
                }
            }
        }
        if(bikeAreaParam != null && bikeAreaParam.getUserStopBikeRfidEnabled()) {
            rideClose.setAreaCheckResult(CommonConstant.TWO);
            rideClose.setCloseCheckResult(CommonConstant.ONE);
            // 停车规范检查项
            JSONObject closeCheckItem = new JSONObject();
            closeCheckItem.put("userStopBikeRfidEnabled", bikeAreaParam.getUserStopBikeRfidEnabled());
            rideClose.setCloseCheckItem(closeCheckItem.toJSONString());

            if(StrUtil.isBlank(deviceBike.getRfidNo())) {
                rideClose.setAreaCheckResult(CommonConstant.ONE);
                rideClose.setCloseCheckResult(CommonConstant.ZERO);
                rideClose.setPayDispatchMoney(isDispatch);
                rideClose.setDispatchType(CommonConstant.ONE);
                JSONObject closeCheckRule = new JSONObject();
                closeCheckRule.put("code", 500);
                closeCheckRule.put("message", "站点rfid停车检查未通过");
                rideClose.setCloseCheckRule(closeCheckRule.toJSONString());

                // 尚未同意调度费 发送还车失败语音 防止与锁车指令冲突
                if (isDispatch == null || CommonConstant.ZERO.equals(isDispatch)) {
                    this.sendStopBikeVoice(deviceBike.getAgentId(), deviceBike.getBikeNo(), "RFID还车失败提醒");
                }

                // 不符合停车规范时 根据配置是否有站外调度费 来提醒用户
                BigDecimal stationDispatchFee = BigDecimal.ZERO;
                if(priceRule.getIsOpenDispatch().equals(CommonConstant.ONE)) {
                    if (priceRule.getStationDispatchFee().compareTo(new BigDecimal(0)) > 0) {
                        if (isDispatch == null || isDispatch.equals(CommonConstant.ZERO)) {

                            stationDispatchFee = priceRule.getStationDispatchFee();
                            // 获取当前车辆最新订单
                            EbRideOrder ebRideOrder = rideOrderService.getOne(new LambdaQueryWrapper<EbRideOrder>()
                                    .eq(EbRideOrder::getBikeId, deviceBike.getId())
                                    .orderByDesc(EbRideOrder::getId)
                                    .last("limit 0,1"));
                            if (ebRideOrder != null) {
                                Long diffMinute = DateUtil.between(ebRideOrder.getOpenTime(), DateUtil.date(), DateUnit.SECOND);
                                if ((diffMinute <= priceRule.getFreeMinuteRiding() * 60) && priceRule.getIsRidingDispatch().equals(CommonConstant.ZERO)) {
                                    stationDispatchFee = BigDecimal.ZERO;
                                }
                            }
                            JSONObject data = new JSONObject();
                            data.put("fee", stationDispatchFee);
                            throw new BadResponseException(522, "当前不在停车点，停车需支付" + stationDispatchFee + "元调度费", data);
                        }
                        stationDispatchFee = priceRule.getStationDispatchFee();
                    }
                }else {
                    if (isMember) {
                        throw new BadResponseException(502, "当前不在停车点，请到P点停车");
                    }
                }
                rideClose.setDispatchMoney(stationDispatchFee);
            }
        }
    }

    private void checkOperationStation(Boolean isMember, EbRideClose rideClose, EbDeviceBike deviceBike, Integer isDispatch, EbPriceRule priceRule) {
        rideClose.setAreaCheckResult(CommonConstant.TWO);
        if (deviceBike.getStationId() == null) {
            rideClose.setAreaCheckResult(CommonConstant.ONE);
            rideClose.setPayDispatchMoney(isDispatch);
            rideClose.setDispatchType(CommonConstant.ONE);
            if(isDispatch == null || isDispatch.equals(CommonConstant.ZERO)) {
                this.sendStopBikeVoice(deviceBike.getAgentId(), deviceBike.getBikeNo(), "站外还车提醒");
            }
            BigDecimal stationDispatchFee = BigDecimal.ZERO;
            // 系统允许站外
            if (priceRule.getIsOpenDispatch().equals(CommonConstant.ONE)) {
                // 有调度费
                if (priceRule.getStationDispatchFee().compareTo(new BigDecimal(0)) > 0) {
                    if (isDispatch == null || isDispatch.equals(CommonConstant.ZERO)) {
                        stationDispatchFee = priceRule.getStationDispatchFee();
                        // 获取当前车辆最新订单
                        EbRideOrder ebRideOrder = rideOrderService.getOne(new LambdaQueryWrapper<EbRideOrder>()
                                .eq(EbRideOrder::getBikeId, deviceBike.getId())
                                .orderByDesc(EbRideOrder::getId)
                                .last("limit 0,1"));
                        if (ebRideOrder != null) {
                            Long diffMinute = DateUtil.between(ebRideOrder.getOpenTime(), DateUtil.date(), DateUnit.SECOND);
                            if ((diffMinute <= priceRule.getFreeMinuteRiding() * 60) && priceRule.getIsRidingDispatch().equals(CommonConstant.ZERO)) {
                                stationDispatchFee = BigDecimal.ZERO;
                            }
                        }
                        JSONObject data = new JSONObject();
                        data.put("fee", stationDispatchFee);
                        throw new BadResponseException(512, "当前不在停车点，停车需支付" + stationDispatchFee + "元调度费", data);
                    }
                    stationDispatchFee = priceRule.getStationDispatchFee();
                }
            } else {
                if (isMember) {
                    throw new BadResponseException(502, "当前不在停车点，请到P点停车");
                }
            }
            rideClose.setDispatchMoney(stationDispatchFee);
        }
    }

    private void checkOperationArea(Boolean isMember, EbRideClose rideClose, EbDeviceBike deviceBike, Integer isDispatch, EbPriceRule priceRule) {
        rideClose.setAreaCheckResult(CommonConstant.TWO);
        if (deviceBike.getIsInArea().equals(CommonConstant.ZERO)) {
            rideClose.setAreaCheckResult(CommonConstant.ONE);
            rideClose.setPayDispatchMoney(isDispatch);
            rideClose.setDispatchType(CommonConstant.TWO);

            // 发送还车失败语音
            if (isDispatch == null || CommonConstant.ZERO.equals(isDispatch)) {
                this.sendStopBikeVoice(deviceBike.getAgentId(), deviceBike.getBikeNo(), "服务区还车提醒");
            }

            // 系统允许超区
            BigDecimal stationDispatchFee = BigDecimal.ZERO;
            if (priceRule.getIsOpenAreaDispatch() != null && priceRule.getIsOpenAreaDispatch().equals(CommonConstant.ONE)) {
                // 有调度费
                if (priceRule.getSuperDispatchFee() != null && priceRule.getSuperDispatchFee().compareTo(new BigDecimal(0)) > 0) {
                    if (isDispatch == null || isDispatch.equals(CommonConstant.ZERO)) {
                        JSONObject data = new JSONObject();
                        data.put("fee", priceRule.getSuperDispatchFee());
                        throw new BadResponseException(511, "当前不在服务区，停车需支付" + priceRule.getSuperDispatchFee() + "元调度费", data);
                    }
                    stationDispatchFee = priceRule.getSuperDispatchFee();
                }
            } else {
                if (isMember) {
                    throw new BadResponseException(501, "当前不在服务区，请到P点停车");
                }
            }
            rideClose.setDispatchMoney(stationDispatchFee);
        }
    }

    private void sendStopBikeVoice(Integer agentId, String bikeNo, String sysName) {
        try {
            SendBikeCommandForm commandForm = new SendBikeCommandForm()
                    .setCommand(DeviceCommandEnum.RETURN_FAIL_VOICE.getType())
                    .setAgentId(agentId)
                    .setBikeNo(bikeNo)
                    .setUserId(0)
                    .setUserName(sysName)
                    .setUserType(UserTypeEnum.SYS.getCode());
            iotBikeClient.sendBikeCommand(commandForm);
        }catch (Exception ex) {
            log.info("发送语音指令:{}", ex.getMessage());
        }
    }

    private void checkBikeHelmet(Boolean superRole, EbRideClose rideClose, Integer payHelmetMoney, EbPriceRule priceRule, EbDeviceBike deviceBike) {
        if (payHelmetMoney == null || payHelmetMoney.equals(CommonConstant.ZERO)) {
            rideClose.setHelmetCheckResult(CommonConstant.ONE);
            rideClose.setPayHelmetMoney(payHelmetMoney == null? CommonConstant.ZERO : payHelmetMoney);
            // 发送归返头盔语音
            SendBikeCommandForm commandForm = new SendBikeCommandForm()
                    .setCommand(DeviceCommandEnum.HELMET_LOCK_RETURN_VOICE.getType())
                    .setAgentId(deviceBike.getAgentId())
                    .setBikeNo(deviceBike.getBikeNo())
                    .setUserId(0)
                    .setUserName("系统")
                    .setUserType(UserTypeEnum.SYS.getCode());
            iotBikeClient.sendBikeCommand(commandForm);

            if (priceRule.getIsNoHelmet() != null && priceRule.getIsNoHelmet().equals(CommonConstant.ONE)) {
                JSONObject data = new JSONObject();
                data.put("fee", priceRule.getHelmetPay());
                throw new BadResponseException(517, "头盔未关锁或头盔摆放位置不正确" + priceRule.getHelmetPay() + "元", data);
            }else {
                throw new BadResponseException(516, "头盔未关锁或头盔摆放位置不正确");
            }
        } else {
            rideClose.setHelmetCheckResult(CommonConstant.ONE);
            rideClose.setPayHelmetMoney(payHelmetMoney);
            if(superRole) {
                rideClose.setHelmetMoney(priceRule.getHelmetPay());
            } else {
                rideClose.setHelmetMoney(priceRule.getSysHelmetPay());
            }
        }
    }

    private void endCheck(EbRideClose rideClose, String message) {
        JSONObject portReturnResult = new JSONObject();
        portReturnResult.put("code", 200);
        portReturnResult.put("message", message);

        rideClose.setPortReturnResult(portReturnResult.toJSONString());
        Date portEndTime = new Date();
        rideClose.setPortEndTime(portEndTime);
        rideClose.setPortTakeTime((int)DateUtil.between(rideClose.getPortStartTime() != null? rideClose.getPortStartTime() : DateUtil.date(), portEndTime, DateUnit.MS, true));
    }
}
